package main.database;

import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map.Entry;

public class Database 
{
	private static final Database instance = new Database();
	private Connection conn;
	private HashMap<String, PreparedStatement> statements;
	
	private Database() {}
	
	public void initialize(DatabaseTuner tuner) throws Exception
	{
		Class.forName(tuner.getDriver());
		conn = DriverManager.getConnection(tuner.getCs());
		prepareStatements(tuner);
	}
	
	private void prepareStatements(DatabaseTuner tuner) throws Exception
	{
		HashMap<String, String> queries = tuner.loadQueries();
		statements = new HashMap<String, PreparedStatement>();
		for(Entry<String, String> entry: queries.entrySet())
		{
			statements.put(entry.getKey(), conn.prepareStatement(entry.getValue()));
		}
	}
	
	public ResultSet executeQuery(String queryName, Object[] params) throws Exception 
	{
		PreparedStatement stmt = statements.get(queryName);
		if(stmt == null) throw new Exception("Query named as \"" + queryName + "\" not found");
		if (params != null) for(int i = 0; i < params.length; i++) stmt.setObject(i + 1, params[i]);
		return stmt.executeQuery();
	}
	
	public int executeChange(String queryName, Object[] params) throws Exception 
	{
		PreparedStatement stmt = statements.get(queryName);
		if(stmt == null) throw new Exception("Query named as \"" + queryName + "\" not found");
		if (params != null) for(int i = 0; i < params.length; i++) stmt.setObject(i + 1, params[i]);
		return stmt.executeUpdate();
	}
	
	public static Database getInstance() 
	{
		return instance;
	}
	
	private void closeStatements() 
	{
		for(PreparedStatement stmt: statements.values()) 
		{
			try 
			{
				stmt.close();
			}
			catch(Exception e) {}
		}
	}

	public void release() 
	{
		closeStatements();
		try 
		{
    		if(conn != null && !conn.isClosed()) conn.close();
		}
		catch(Exception e) {}
	}
	
	public Blob createBlob() throws SQLException
	{
		return conn.createBlob();
	}
}
